﻿using System;
using System.Collections.Generic;
using System.Linq;
using WaveSim.Core.Equations.Galerkin;

namespace WaveSim.Core.Data.Parser
{
    public class CodeParser
    {
        private static Dictionary<string, Type> typesPool;

        public IEnumerable<String> Items
        {
            get
            {
                return typesPool.Keys.OrderBy(item => item.ToString()).ToList();
            }
        }

        static CodeParser()
        {
            typesPool = new Dictionary<string, Type>();
            foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                foreach (Type t in assembly.GetTypes())
                {
                    if (typeof(ICodable).IsAssignableFrom(t) && t.IsClass)
                    {
                        typesPool.Add(t.Name, t);
                    }
                }
            }
        }

        public BaseDielectric GetStructure(string code)
        {
            Composite composite = new Composite();
            foreach (var codePart in code.Split('#'))
            {
                if (codePart == String.Empty)
                {
                    continue;
                }

                if (codePart.IndexOf('\n') == -1)
                {
                    continue;
                }

                string name = Process(codePart.Substring(0, codePart.IndexOf('\n')));
                if (typesPool.ContainsKey(name))
                {
                    ICodable instance = (ICodable)Activator.CreateInstance(typesPool[name]);
                    if (instance is BaseDielectric)
                    {
                        var dielectric = instance.Decode(codePart) as BaseDielectric;
                        if (dielectric != null)
                        {
                            composite.Components.Add(dielectric);
                        }
                    }
                }
            }
            return composite;
        }

        public WaveGuide GetWaveGuide(string code)
        {
            Composite composite = new Composite();
            foreach (var codePart in code.Split('#'))
            {
                if (codePart == String.Empty)
                {
                    continue;
                }

                string name = Process(codePart.Substring(0, codePart.IndexOf('\n')));
                if (typesPool.ContainsKey(name))
                {
                    var instance = (ICodable)Activator.CreateInstance(typesPool[name]);
                    if (instance is WaveGuide)
                    {
                        var wg = instance.Decode(codePart) as WaveGuide;
                        if (wg != null)
                        {
                            return wg;
                        }
                    }
                }
            }
            return null;
        }

        private static string Process(string str)
        {
            return str
                .Replace("\r", String.Empty)
                .Replace("\t", String.Empty)
                .Replace("\n", String.Empty)
                .Trim();
        }
    }
}
